﻿/********************************************************************************/
// <copyright file="RepositoryFactory.cs" company="Asia E-Business Solutions">
//     Copyright © 2012. All right reserved
// </copyright>
//
// <history>
//  <change who="Hieu Nguyen" date="11/12/2012 12:13:14 PM">Created</change>
// <history>
/********************************************************************************/

namespace JLL.China.Infrastructure.RepositoryFramework
{
    using System.Collections.Generic;
    using JLL.China.Infrastructure.DomainBase;
    using JLL.China.Infrastructure.UnitOfWork;
    using System;

    public static class RepositoryFactory
    {
        // Dictionary to enforce the singleton pattern
        private static Dictionary<string, object> repositories = new Dictionary<string, object>();

        /// <summary>
        /// Gets the repository.
        /// </summary>
        /// <typeparam name="TRepository">The type of the repository.</typeparam>
        /// <param name="unitOfWork">The unit of work.</param>
        /// <returns></returns>
        public static TRepository GetRepository<TRepository, E, T>(IUnitOfWork<T> unitOfWork)
            where TRepository : IRepository<E, T>
            where E : IAggregateRoot<T>
            where T : new()
        {
            // Initialize the provider's default value
            TRepository repository = default(TRepository);

            string interfaceShortName = typeof(TRepository).Name;

            // See if the provider was already created and is in the cache
            if (!RepositoryFactory.repositories.ContainsKey(interfaceShortName))
            {
                repository = ObjectFactory.Resolve<TRepository>();
                if (unitOfWork != null)
                {
                    repository.SetUnitOfWork(unitOfWork);
                }
                else if (repository.UnitOfWork == null)
                {
                    throw new Exception("UnitOfWork was not set and provided unitOfWork is null");
                }
                // Add the new provider instance to the cache
                RepositoryFactory.repositories.Add(interfaceShortName, repository);
            }
            else
            {
                repository = (TRepository)RepositoryFactory.repositories[interfaceShortName];
                if (repository.UnitOfWork == null)
                {
                    throw new Exception("UnitOfWork was not set");
                }
            }
            return repository;
        }


        /// <summary>
        /// Gets the repository.
        /// </summary>
        /// <typeparam name="TRepository">The type of the repository.</typeparam>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static TRepository GetRepository<TRepository, E, T>()
            where TRepository : IRepository<E, T>
            where E : IAggregateRoot<T>
            where T : new()
        {
            return GetRepository<TRepository, E, T>(null);
        }
    }
}
